source(file.path(my_working_dir,"run_downloader.R"))
## Added 2 new Ironclad run files
## Added 2 new Silent run files
## Added 1 new Defect run files
## Added 0 new Watcher run files
Filtering out these runs: * Non ascension 20 runs * Runs that ended before floor 6 (considering these not serious runs) * Runs that were victorious but didn’t defeat the heart
storage_dir = file.path(my_working_dir,"all_run_history/")
#make list of all valid ironclad runs
ironclad_list = list()
ironclad_files = list.files(file.path(storage_dir,"IRONCLAD"),full.names=T)
for(fn in ironclad_files){
result = fromJSON(file = fn)
if(result$ascension_level == 20 && result$floor_reached >= 6){
if(!(result$victory == TRUE && result$floor_reached < 52)){
ironclad_list[result$play_id] = list(result)
}
}
}
cat(sprintf("%s total Ironclad runs\n",length(ironclad_list)))
## 47 total Ironclad runs
#make list of all valid silent runs
silent_list = list()
silent_files = list.files(file.path(storage_dir,"THE_SILENT"),full.names=T)
for(fn in silent_files){
result = fromJSON(file = fn)
if(result$ascension_level == 20 && result$floor_reached >= 6){
if(!(result$victory == TRUE && result$floor_reached < 52)){
silent_list[result$play_id] = list(result)
}
}
}
cat(sprintf("%s total Silent runs\n",length(silent_list)))
## 67 total Silent runs
#make list of all valid defect runs
defect_list = list()
defect_files = list.files(file.path(storage_dir,"DEFECT"),full.names=T)
for(fn in defect_files){
result = fromJSON(file = fn)
if(result$ascension_level == 20 && result$floor_reached >= 6){
if(!(result$victory == TRUE && result$floor_reached < 52)){
defect_list[result$play_id] = list(result)
}
}
}
cat(sprintf("%s total Defect runs\n",length(defect_list)))
## 61 total Defect runs
#make list of all valid watcher runs
watcher_list = list()
watcher_files = list.files(file.path(storage_dir,"WATCHER"),full.names=T)
for(fn in watcher_files){
result = fromJSON(file = fn)
if(result$ascension_level == 20 && result$floor_reached >= 6){
if(!(result$victory == TRUE && result$floor_reached < 52)){
watcher_list[result$play_id] = list(result)
}
}
}
cat(sprintf("%s total Watcher runs\n",length(watcher_list)))
## 16 total Watcher runs
#make table for each character with all the 1D attributes (will ignore other stuff for now)
onedim_cols = c("floor_reached","victory","killed_by","local_time","neow_cost","neow_bonus","campfire_rested","campfire_upgraded",
"purchased_purges","player_experience","gold","playtime","seed_played","score","timestamp")
ironclad_tab = rbindlist(lapply(ironclad_list, function(x){
x[onedim_cols]
}),fill=T)
## Warning in rbindlist(lapply(ironclad_list, function(x) {: Column 3 ['NA'] of
## item 5 is length 0. This (and 9 others like it) has been filled with NA (NULL
## for list columns) to make each item uniform.
silent_tab = rbindlist(lapply(silent_list, function(x){
x[onedim_cols]
}),fill=T)
## Warning in rbindlist(lapply(silent_list, function(x) {: Column 3 ['NA'] of item
## 18 is length 0. This (and 11 others like it) has been filled with NA (NULL for
## list columns) to make each item uniform.
defect_tab = rbindlist(lapply(defect_list, function(x){
x[onedim_cols]
}),fill=T)
## Warning in rbindlist(lapply(defect_list, function(x) {: Column 3 ['NA'] of item
## 1 is length 0. This (and 11 others like it) has been filled with NA (NULL for
## list columns) to make each item uniform.
watcher_tab = rbindlist(lapply(watcher_list, function(x){
x[onedim_cols]
}),fill=T)
## Warning in rbindlist(lapply(watcher_list, function(x) {: Column 3 ['NA'] of item
## 1 is length 0. This (and 6 others like it) has been filled with NA (NULL for
## list columns) to make each item uniform.
ironclad_tab$character = "Ironclad"
silent_tab$character = "Silent"
defect_tab$character = "Defect"
watcher_tab$character = "Watcher"
#sort with newest runs on top
ironclad_tab = ironclad_tab[order(timestamp,decreasing=T)]
silent_tab = silent_tab[order(timestamp,decreasing=T)]
defect_tab = defect_tab[order(timestamp,decreasing=T)]
watcher_tab = watcher_tab[order(timestamp,decreasing=T)]
#put them into one list
allchar_list = list("Ironclad"=ironclad_tab, "Silent"=silent_tab, "Defect"=defect_tab, "Watcher"=watcher_tab)
char_vec = c("Ironclad","Silent","Defect","Watcher")
all_timestamps = c()
df = setNames(data.frame(matrix(ncol = 5, nrow = 3)), c(char_vec,"Rotating"))
rownames(df) = c("Overall","Last50","Last25")
for(char in char_vec){
mychar_tab = allchar_list[[char]]
all_timestamps = c(all_timestamps,mychar_tab[,timestamp])
tot = nrow(mychar_tab)
win_all = sum(mychar_tab[,victory])/tot
win_50 = sum(mychar_tab[,victory][1:min(50,tot)])/min(50,tot)
win_25 = sum(mychar_tab[,victory][1:min(25,tot)])/min(25,tot)
df[char] = c(win_all,win_50,win_25)
}
#get rotating stats
all_timestamps = sort(all_timestamps,decreasing=T)
tot_curr = winsall_curr = wins50_curr = wins25_curr = 0
for(char in char_vec){
mychar_tab = allchar_list[[char]]
tot_curr = tot_curr + nrow(mychar_tab)
winsall_curr = winsall_curr + sum(mychar_tab$victory)
wins50_curr = wins50_curr + sum(mychar_tab[timestamp %in% all_timestamps[1:50]]$victory)
wins25_curr = wins25_curr + sum(mychar_tab[timestamp %in% all_timestamps[1:25]]$victory)
}
df["Rotating"] = c(winsall_curr/tot_curr,wins50_curr/50,wins25_curr/25)
#save winrate stats over time
write.csv(df,file = file.path(my_working_dir,"winrate_history",paste0("winrate_",unlist(strsplit(as.character(Sys.time()), split=" "))[1],".csv")))
#plot this
plotdata = melt(data.table(df,keep.rownames = T),id.vars="rn")
colnames(plotdata) = c("Number of Runs","Character","Winrate")
plotdata$Winrate = plotdata$Winrate*100
plotdata$`Number of Runs` = factor(plotdata$`Number of Runs`,levels = c("Overall","Last50","Last25"),ordered=T)
p1 = ggplot(plotdata, aes(fill=`Number of Runs`, y=Winrate, x=Character)) +
geom_bar(position="dodge", stat="identity") +
scale_fill_manual(values=c("#7dcfb6", "#f79256", "#fbd1a2")) +
ylab("Winrate (%)")
ggplotly(p1)
#TODO - try to annotate this with the total number of runs for each bar
curr_winstreaks = max_winstreaks = curr_lossstreaks = max_lossstreaks = vector("numeric")
## individual character winstreaks ##
for(char in char_vec){
mychar_tab = allchar_list[[char]]
mychar_tab = mychar_tab[order(timestamp,decreasing=T)]
my_rle = rle(mychar_tab$victory)
all_wins = my_rle$length[my_rle$values == TRUE]
all_losses = my_rle$length[my_rle$values == FALSE]
#get current streaks
if(mychar_tab$victory[1]){ #if most recent run was a victory
curr_winstreaks = append(curr_winstreaks,all_wins[1])
curr_lossstreaks = append(curr_lossstreaks,0)
}else{
curr_winstreaks = append(curr_winstreaks,0)
curr_lossstreaks = append(curr_lossstreaks,all_losses[1])
}
#get max streaks
max_winstreaks = append(max_winstreaks, max(all_wins))
max_lossstreaks = append(max_lossstreaks, max(all_losses))
}
## rotating winstreak, and determine which character I need to play next to continue rotating ##
get_rotating_winstreak <- function(runtab, get_next_char=FALSE){
runtab = runtab[order(timestamp,decreasing=F)] #forward chronological order
#remove any consecutive runs with the same character (e.g. 2 wins with ironclad and 1 win with silent = rotating streak of 2)
my_char_vec = runtab$character
my_char_vec = rle(my_char_vec)$values
my_char_vec = sapply(my_char_vec, function(x) switch(x,"Ironclad"=1,"Silent"=2,"Defect"=3,"Watcher"=4))
#return 1 if the length of char_vec is 1
if(length(my_char_vec) <= 1){
if(get_next_char){
char_next = switch(my_char_vec[1],"1"="Silent","2"="Defect","3"="Watcher","4"="Ironclad")
return(list(1,char_next))
}else{
return(1)
}
}
#count max length that follows the correct ordering
nwins_curr = nwins_max = 1
most_recent_char = char_curr_max = my_char_vec[1]
for(i in 2:length(my_char_vec)){
char_curr = my_char_vec[i]
if(char_curr != 1){
if(char_curr - most_recent_char == 1){ #correct order
nwins_curr = nwins_curr+1
}else{ #incorrect order - reset
nwins_curr = 1
}
}else if(char_curr == 1){
if(most_recent_char == 4){ #correct order
nwins_curr = nwins_curr+1
}else{ #incorrect order - reset
nwins_curr = 1
}
}
if(nwins_curr > nwins_max){
nwins_max = nwins_curr
#get current character
char_curr_max = char_curr
}
most_recent_char = char_curr
}
if(get_next_char){
char_next = switch(char_curr_max,"1"="Silent","2"="Defect","3"="Watcher","4"="Ironclad")
return(list(nwins_max,char_next))
}else{
return(nwins_max)
}
}
alltab = rbindlist(allchar_list,fill=TRUE)
alltab = alltab[order(timestamp,decreasing=T)]
consec_ind = alltab[ , .(start = .I[1], end = .I[.N]), by = rleid(victory)][, rleid := NULL][]
#check for current rotating winstreak
curr_runs = alltab[as.numeric(consec_ind[1,1]):as.numeric(consec_ind[1,2])]
if(curr_runs$victory[1]){ #most recent set of runs are victories, now need to determine how many of those count towards the rotating winstreak
curr_rot_info = get_rotating_winstreak(curr_runs,get_next_char=TRUE)
curr_winstreaks = append(curr_winstreaks,curr_rot_info[[1]])
}else{ #most recent run is a loss
curr_winstreaks = append(curr_winstreaks,0)
}
#check for max rotating winstreak
n_rot_wins_max = 0
for(i in 1:nrow(consec_ind)){
curr_runs = alltab[as.numeric(consec_ind[i,1]):as.numeric(consec_ind[i,2])]
if(curr_runs$victory[1]){
n_rot_wins = get_rotating_winstreak(curr_runs)
if(n_rot_wins > n_rot_wins_max){n_rot_wins_max = n_rot_wins}
}
}
max_winstreaks = append(max_winstreaks,n_rot_wins_max)
CURRENT ROTATING STREAK:
[1] “There is no active rotating streak ” There is no active rotating
streak
CURRENT WIN STREAKS:
CURRENT LOSS STREAKS:
The Ironclad is currently on a loss streak of 1
The Silent is currently on a loss streak of 1
The Defect is currently on a loss streak of 2
The Watcher is currently on a loss streak of 1
PERSONAL BEST/WORST STATS:
The max rotating streak is 5 consecutive wins
The Ironclad’s max streaks are 4 consecutive wins and 13 consecutive
losses
The Silent’s max streaks are 3 consecutive wins and 17 consecutive
losses
The Defect’s max streaks are 2 consecutive wins and 20 consecutive
losses
The Watcher’s max streaks are 3 consecutive wins and 5 consecutive
losses